home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint96sb.zoo / src / biosfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-18  |  32.7 KB  |  1,471 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith. All rights reserved.
  3.  */
  4.  
  5. /* simple biosfs.c */
  6.  
  7. #include "mint.h"
  8.  
  9. extern struct kerinfo kernelinfo;    /* see main.c */
  10.  
  11. static long    ARGS_ON_STACK bios_root    P_((int drv, fcookie *fc));
  12. static long    ARGS_ON_STACK bios_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  13. static long    ARGS_ON_STACK bios_getxattr    P_((fcookie *fc, XATTR *xattr));
  14. static long    ARGS_ON_STACK bios_chattr    P_((fcookie *fc, int attrib));
  15. static long    ARGS_ON_STACK bios_chown    P_((fcookie *fc, int uid, int gid));
  16. static long    ARGS_ON_STACK bios_chmode    P_((fcookie *fc, unsigned mode));
  17. static long    ARGS_ON_STACK bios_rmdir    P_((fcookie *dir, const char *name));
  18. static long    ARGS_ON_STACK bios_remove    P_((fcookie *dir, const char *name));
  19. static long    ARGS_ON_STACK bios_getname    P_((fcookie *root, fcookie *dir, char *pathname));
  20. static long    ARGS_ON_STACK bios_rename    P_((fcookie *olddir, char *oldname,
  21.                     fcookie *newdir, const char *newname));
  22. static long    ARGS_ON_STACK bios_opendir    P_((DIR *dirh, int flags));
  23. static long    ARGS_ON_STACK bios_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *fc));
  24. static long    ARGS_ON_STACK bios_rewinddir    P_((DIR *dirh));
  25. static long    ARGS_ON_STACK bios_closedir    P_((DIR *dirh));
  26. static long    ARGS_ON_STACK bios_pathconf    P_((fcookie *dir, int which));
  27. static long    ARGS_ON_STACK bios_dfree    P_((fcookie *dir, long *buf));
  28. static DEVDRV *    ARGS_ON_STACK bios_getdev    P_((fcookie *fc, long *devspecial));
  29. static long    ARGS_ON_STACK bios_fscntl    P_((fcookie *, const char *, int, long));
  30. static long    ARGS_ON_STACK bios_symlink    P_((fcookie *, const char *, const char *));
  31. static long    ARGS_ON_STACK bios_readlink    P_((fcookie *, char *, int));
  32.  
  33. static long    ARGS_ON_STACK bios_topen    P_((FILEPTR *f));
  34. static long    ARGS_ON_STACK bios_twrite    P_((FILEPTR *f, const char *buf, long bytes));
  35. static long    ARGS_ON_STACK bios_tread    P_((FILEPTR *f, char *buf, long bytes));
  36. static long    ARGS_ON_STACK bios_nwrite    P_((FILEPTR *f, const char *buf, long bytes));
  37. static long    ARGS_ON_STACK bios_nread    P_((FILEPTR *f, char *buf, long bytes));
  38. static long    ARGS_ON_STACK bios_ioctl    P_((FILEPTR *f, int mode, void *buf));
  39. static long    ARGS_ON_STACK bios_select    P_((FILEPTR *f, long p, int mode));
  40. static void    ARGS_ON_STACK bios_unselect    P_((FILEPTR *f, long p, int mode));
  41. static long    ARGS_ON_STACK bios_tseek    P_((FILEPTR *f, long where, int whence));
  42.  
  43. long    ARGS_ON_STACK null_open    P_((FILEPTR *f));
  44. long    ARGS_ON_STACK null_write    P_((FILEPTR *f, const char *buf, long bytes));
  45. long    ARGS_ON_STACK null_read    P_((FILEPTR *f, char *buf, long bytes));
  46. long    ARGS_ON_STACK null_lseek    P_((FILEPTR *f, long where, int whence));
  47. long    ARGS_ON_STACK null_ioctl    P_((FILEPTR *f, int mode, void *buf));
  48. long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  49. long    ARGS_ON_STACK null_close    P_((FILEPTR *f, int pid));
  50. long    ARGS_ON_STACK null_select    P_((FILEPTR *f, long p, int mode));
  51. void    ARGS_ON_STACK null_unselect    P_((FILEPTR *f, long p, int mode));
  52.  
  53. static long ARGS_ON_STACK mouse_open    P_((FILEPTR *f));
  54. static long ARGS_ON_STACK mouse_read    P_((FILEPTR *f, char *buf, long nbytes));
  55. static long ARGS_ON_STACK mouse_ioctl P_((FILEPTR *f, int mode, void *buf));
  56. static long ARGS_ON_STACK mouse_close P_((FILEPTR *f, int pid));
  57. static long ARGS_ON_STACK mouse_select P_((FILEPTR *f, long p, int mode));
  58. static void ARGS_ON_STACK mouse_unselect P_((FILEPTR *f, long p, int mode));
  59.  
  60. /* device driver for BIOS terminals */
  61.  
  62. DEVDRV bios_tdevice = {
  63.     bios_topen, bios_twrite, bios_tread, bios_tseek, bios_ioctl,
  64.     null_datime, null_close, bios_select, bios_unselect
  65. };
  66.  
  67. /* device driver for BIOS devices that are not terminals */
  68.  
  69. DEVDRV bios_ndevice = {
  70.     null_open, bios_nwrite, bios_nread, null_lseek, bios_ioctl,
  71.     null_datime, null_close, bios_select, bios_unselect
  72. };
  73.  
  74. DEVDRV null_device = {
  75.     null_open, null_write, null_read, null_lseek, null_ioctl,
  76.     null_datime, null_close, null_select, null_unselect
  77. };
  78.  
  79. DEVDRV mouse_device = {
  80.     mouse_open, null_write, mouse_read, null_lseek, mouse_ioctl,
  81.     null_datime, mouse_close, mouse_select, mouse_unselect
  82. };
  83.  
  84. /* this special driver is checked for in dosfile.c, and indicates that
  85.  * a dup operation is actually wanted rather than an open
  86.  */
  87. DEVDRV fakedev;
  88.  
  89. #ifdef FASTTEXT
  90. extern DEVDRV screen_device;    /* see fasttext.c */
  91. #endif
  92.  
  93. FILESYS bios_filesys = {
  94.     (FILESYS *)0,
  95.     0,
  96.     bios_root,
  97.     bios_lookup, nocreat, bios_getdev, bios_getxattr,
  98.     bios_chattr, bios_chown, bios_chmode,
  99.     nomkdir, bios_rmdir, bios_remove, bios_getname, bios_rename,
  100.     bios_opendir, bios_readdir, bios_rewinddir, bios_closedir,
  101.     bios_pathconf, bios_dfree, nowritelabel, noreadlabel,
  102.     bios_symlink, bios_readlink, nohardlink, bios_fscntl, nodskchng
  103. };
  104.  
  105.  
  106. struct tty con_tty, aux_tty, midi_tty;
  107. struct tty sccb_tty, scca_tty, ttmfp_tty;
  108.  
  109. #define BNAME_MAX    13
  110.  
  111. struct bios_file {
  112.     char     name[BNAME_MAX+1];    /* device name */
  113.     DEVDRV *device;            /* device driver for device */
  114.     short    private;        /* extra info for device driver */
  115.     ushort    flags;            /* flags for device open */
  116.     struct tty *tty;        /* tty structure (if appropriate) */
  117.     struct bios_file *next;
  118. };
  119.  
  120. struct bios_file BDEV[] = {
  121.  
  122. /* "real" bios devices present on all machines */
  123.     {"centr", &bios_ndevice, 0, 0, 0, 0},
  124.     {"console", &bios_tdevice, 2, O_TTY, &con_tty, 0},
  125.     {"midi", &bios_tdevice, 3, O_TTY, &midi_tty, 0},
  126.     {"kbd", &bios_ndevice, 4, 0, 0, 0},
  127. /* devices that duplicate handles */
  128.     {"prn", &fakedev, -3, 0, 0, 0}, /* handle -3 (printer) */
  129.     {"aux", &fakedev, -2, 0, 0, 0}, /* handle -2 (aux. terminal) */
  130.     {"con", &fakedev, -1, 0, 0, 0}, /* handle -1 (control terminal) */
  131.     {"tty", &fakedev, -1, 0, 0, 0}, /* the Unix name for it */
  132.     {"stdin", &fakedev, 0, 0, 0, 0},  /* handle 0 (stdin) */
  133.     {"stdout", &fakedev, 1, 0, 0, 0}, /* handle 1 (stdout) */
  134.     {"stderr", &fakedev, 2, 0, 0, 0}, /* handle 2 (stderr) */
  135.  
  136. /* other miscellaneous devices */
  137.     {"mouse", &mouse_device, 0, 0, 0, 0},
  138.     {"null", &null_device, 0, 0, 0, 0},
  139.  
  140. #ifdef FASTTEXT
  141. /* alternate console driver */
  142.     {"fasttext", &screen_device, 2, O_TTY, &con_tty, 0},
  143. #endif
  144.  
  145. /* serial port things *must* come last, because not all of these
  146.  * are present on all machines (except for modem1, which does however
  147.  * have a different device number on TTs and STs)
  148.  */
  149.     {"modem1", &bios_tdevice, 6, O_TTY, &aux_tty, 0},
  150.     {"modem2", &bios_tdevice, 7, O_TTY, &sccb_tty, 0},
  151.     {"serial1", &bios_tdevice, 8, O_TTY, &ttmfp_tty, 0},
  152.     {"serial2", &bios_tdevice, 9, O_TTY, &scca_tty, 0},
  153.     {"", 0, 0, 0, 0, 0}
  154. };
  155.  
  156. struct bios_file *broot, *bdevlast;
  157.  
  158. /* a file pointer for BIOS device 1, provided only for insurance
  159.  * in case a Bconmap happens and we can't allocate a new FILEPTR;
  160.  * in most cases, we'll want to build a FILEPTR in the usual
  161.  * way.
  162.  */
  163.  
  164. FILEPTR *defaultaux;
  165.  
  166. void
  167. biosfs_init()
  168. {
  169.     struct bios_file *b;
  170.  
  171.     broot = BDEV;
  172.  
  173.     for (b = broot; b->name[0]; b++) {
  174.         b->next = b+1;
  175.  
  176.     /* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS
  177.      * device 1
  178.      * and ignore the remaining devices, since they're not present
  179.      */
  180.         if (!has_bconmap && b->private == 6) {
  181.             b->private = 1;
  182.             b->next = 0;
  183.             break;
  184.         }
  185.     /* SERIAL2 is not present on the Mega STe */
  186.         if (mch == MEGASTE && b->private == 8) {
  187.             b->next = 0;
  188.             break;
  189.         }
  190.             
  191.     }
  192.     bdevlast = b;
  193.     if (b->name[0] == 0) {
  194.         --b;
  195.         b->next = 0;
  196.     }
  197.     defaultaux = new_fileptr();
  198.     defaultaux->links = 1;        /* so it never gets freed */
  199.     defaultaux->flags = O_RDWR;
  200.     defaultaux->pos = 0;
  201.     defaultaux->devinfo = 0;
  202.     defaultaux->fc.fs = &bios_filesys;
  203.     defaultaux->fc.index = 0;
  204.     defaultaux->fc.aux = 1;
  205.     defaultaux->fc.dev = BIOSDRV;
  206.     defaultaux->dev = &bios_ndevice;
  207. }
  208.  
  209. static long ARGS_ON_STACK 
  210. bios_root(drv, fc)
  211.     int drv;
  212.     fcookie *fc;
  213. {
  214.     if (drv == BIOSDRV) {
  215.         fc->fs = &bios_filesys;
  216.         fc->dev = drv;
  217.         fc->index = 0L;
  218.         return 0;
  219.     }
  220.     fc->fs = 0;
  221.     return EINTRN;
  222. }
  223.  
  224. static long ARGS_ON_STACK 
  225. bios_lookup(dir, name, fc)
  226.     fcookie *dir;
  227.     const char *name;
  228.     fcookie *fc;
  229. {
  230.     struct bios_file *b;
  231.  
  232.     if (dir->index != 0) {
  233.         DEBUG(("bios_lookup: bad directory"));
  234.         return EPTHNF;
  235.     }
  236. /* special case: an empty name in a directory means that directory */
  237. /* so does "." */
  238.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  239.         *fc = *dir;
  240.         return 0;
  241.     }
  242.  
  243. /* another special case: ".." could be a mount point */
  244.     if (!strcmp(name, "..")) {
  245.         *fc = *dir;
  246.         return EMOUNT;
  247.     }
  248.  
  249.     for (b = broot; b; b = b->next) {
  250.         if (!stricmp(b->name, name)) {
  251.             fc->fs = &bios_filesys;
  252.             fc->index = (long)b;
  253.             fc->aux = b->private;
  254.             fc->dev = dir->dev;
  255.             return 0;
  256.         }
  257.     }
  258.     DEBUG(("bios_lookup: name(%s) not found", name));
  259.     return EFILNF;
  260. }
  261.  
  262. static long ARGS_ON_STACK 
  263. bios_getxattr(fc, xattr)
  264.     fcookie *fc;
  265.     XATTR *xattr;
  266. {
  267.     FILEPTR *f;
  268.     struct bios_file *b = (struct bios_file *)fc->index;
  269.  
  270.     xattr->index = fc->index;
  271.     xattr->dev = fc->dev;
  272.     xattr->nlink = 1;
  273.     xattr->uid = xattr->gid = 0;
  274.     xattr->size = xattr->nblocks = 0;
  275.     xattr->blksize = 1;
  276.     xattr->mtime = xattr->atime = xattr->ctime = timestamp;
  277.     xattr->mdate = xattr->adate = xattr->cdate = datestamp;
  278.     if (fc->index == 0) {        /* root directory? */
  279.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  280.         xattr->attr = FA_DIR;
  281.     } else if (b->device == 0) {    /* symbolic link? */
  282.         xattr->mode = S_IFLNK | DEFAULT_DIRMODE;
  283.     } else if (b->device == &fakedev &&
  284.         (f = curproc->handle[b->private]) != 0)
  285.     {
  286.         /* u:\dev\stdin, u:\dev\stdout, etc. */
  287.         (*f->fc.fs->getxattr) (&f->fc, xattr);
  288.         xattr->index = fc->index;
  289.         xattr->dev = fc->dev;
  290.     } else {
  291.         xattr->mode = S_IFCHR | DEFAULT_MODE;
  292.         xattr->attr = 0;
  293.     }
  294.     return 0;
  295. }
  296.  
  297. static long ARGS_ON_STACK 
  298. bios_chattr(fc, attrib)
  299.     fcookie *fc;
  300.     int attrib;
  301. {
  302.     UNUSED(fc); UNUSED(attrib);
  303.     return EACCDN;
  304. }
  305.  
  306. static long ARGS_ON_STACK 
  307. bios_chown(fc, uid, gid)
  308.     fcookie *fc;
  309.     int uid, gid;
  310. {
  311.     UNUSED(fc); UNUSED(uid);
  312.     UNUSED(gid);
  313.     return EINVFN;
  314. }
  315.  
  316. static long ARGS_ON_STACK 
  317. bios_chmode(fc, mode)
  318.     fcookie *fc;
  319.     unsigned mode;
  320. {
  321.     UNUSED(fc); UNUSED(mode);
  322.     return EINVFN;
  323. }
  324.  
  325. long ARGS_ON_STACK 
  326. nomkdir(dir, name, mode)
  327.     fcookie *dir;
  328.     const char *name;
  329.     unsigned mode;
  330. {
  331.     UNUSED(dir); UNUSED(name);
  332.     UNUSED(mode);
  333.     return EACCDN;
  334. }
  335.  
  336. static long ARGS_ON_STACK 
  337. bios_rmdir(dir, name)
  338.     fcookie *dir;
  339.     const char *name;
  340. {
  341.     return bios_remove(dir, name);
  342. }
  343.  
  344. /*
  345.  * MAJOR BUG: we don't check here for removal of devices for which there
  346.  * are still open files
  347.  */
  348.  
  349. static long ARGS_ON_STACK 
  350. bios_remove(dir, name)
  351.     fcookie *dir;
  352.     const char *name;
  353. {
  354.     struct bios_file *b, **lastb;
  355.  
  356.     UNUSED(dir);
  357.     lastb = &broot;
  358.     for (b = broot; b; b = *(lastb = &b->next)) {
  359.         if (!stricmp(b->name, name)) break;
  360.     }
  361.     if (!b) return EFILNF;
  362.  
  363. /* don't allow removal of the basic system devices */
  364.     if (b >= BDEV && b <= bdevlast) {
  365.         return EACCDN;
  366.     }
  367.     *lastb = b->next;
  368.  
  369.     if (b->device == 0 || b->device == &bios_tdevice)
  370.         kfree(b->tty);
  371.  
  372.     kfree(b);
  373.     return 0;
  374. }
  375.  
  376. static long ARGS_ON_STACK 
  377. bios_getname(root, dir, pathname)
  378.     fcookie *root, *dir; char *pathname;
  379. {
  380.     UNUSED(root);
  381.     if (dir->index == 0)
  382.         *pathname = 0;
  383.     else
  384.         strcpy(pathname, ((struct bios_file *)dir->index)->name);
  385.     return 0;
  386. }
  387.  
  388. static long ARGS_ON_STACK 
  389. bios_rename(olddir, oldname, newdir, newname)
  390.     fcookie *olddir;
  391.     char *oldname;
  392.     fcookie *newdir;
  393.     const char *newname;
  394. {
  395.     struct bios_file *b;
  396.  
  397.     UNUSED(olddir); UNUSED(newdir);
  398.  
  399. /* BUG: we should check to see if "newname" already exists */
  400.  
  401.     for (b = broot; b; b = b->next) {
  402.         if (!stricmp(b->name, oldname)) {
  403.             strncpy(b->name, newname, BNAME_MAX);
  404.             return 0;
  405.         }
  406.     }
  407.     return EFILNF;
  408. }
  409.  
  410. static long ARGS_ON_STACK 
  411. bios_opendir(dirh, flags)
  412.     DIR *dirh;
  413.     int flags;
  414. {
  415.     UNUSED(flags);
  416.  
  417.     if (dirh->fc.index != 0) {
  418.         DEBUG(("bios_opendir: bad directory"));
  419.         return EPTHNF;
  420.     }
  421.     return 0;
  422. }
  423.  
  424. static long ARGS_ON_STACK 
  425. bios_readdir(dirh, name, namelen, fc)
  426.     DIR *dirh;
  427.     char *name;
  428.     int namelen;
  429.     fcookie *fc;
  430. {
  431.     struct bios_file *b;
  432.     int giveindex = dirh->flags == 0;
  433.     int i;
  434.  
  435.     b = broot;
  436.     i = dirh->index++;
  437.     while(i-- > 0) {
  438.         if (!b) break;
  439.         b = b->next;
  440.     }
  441.     if (!b) {
  442.         return ENMFIL;
  443.     }
  444.     fc->fs = &bios_filesys;
  445.     fc->index = (long)b;
  446.     fc->aux = b->private;
  447.     fc->dev = dirh->fc.dev;
  448.     if (giveindex) {
  449.         namelen -= (int)sizeof(long);
  450.         if (namelen <= 0)
  451.             return ERANGE;
  452.         *((long *)name) = (long) b;
  453.         name += sizeof(long);
  454.     }
  455.     strncpy(name, b->name, namelen-1);
  456.     if (strlen(b->name) >= namelen)
  457.         return ENAMETOOLONG;
  458.     return 0;
  459. }
  460.  
  461. static long ARGS_ON_STACK 
  462. bios_rewinddir(dirh)
  463.     DIR *dirh;
  464. {
  465.     dirh->index = 0;
  466.     return 0;
  467. }
  468.  
  469. static long ARGS_ON_STACK 
  470. bios_closedir(dirh)
  471.     DIR *dirh;
  472. {
  473.     UNUSED(dirh);
  474.     return 0;
  475. }
  476.  
  477. static long ARGS_ON_STACK 
  478. bios_pathconf(dir, which)
  479.     fcookie *dir;
  480.     int which;
  481. {
  482.     UNUSED(dir);
  483.  
  484.     switch(which) {
  485.     case -1:
  486.         return DP_MAXREQ;
  487.     case DP_IOPEN:
  488.         return UNLIMITED;    /* no limit on BIOS file descriptors */
  489.     case DP_MAXLINKS:
  490.         return 1;        /* no hard links available */
  491.     case DP_PATHMAX:
  492.         return PATH_MAX;
  493.     case DP_NAMEMAX:
  494.         return BNAME_MAX;
  495.     case DP_ATOMIC:
  496.         return 1;        /* no atomic writes */
  497.     case DP_TRUNC:
  498.         return DP_AUTOTRUNC;    /* names are truncated */
  499.     case DP_CASE:
  500.         return DP_CASEINSENS;    /* not case sensitive */
  501.     default:
  502.         return EINVFN;
  503.     }
  504. }
  505.  
  506. static long ARGS_ON_STACK 
  507. bios_dfree(dir, buf)
  508.     fcookie *dir;
  509.     long *buf;
  510. {
  511.     UNUSED(dir);
  512.  
  513.     buf[0] = 0;    /* number of free clusters */
  514.     buf[1] = 0;    /* total number of clusters */
  515.     buf[2] = 1;    /* sector size (bytes) */
  516.     buf[3] = 1;    /* cluster size (sectors) */
  517.     return 0;
  518. }
  519.  
  520. /*
  521.  * BIOS Dcntl() calls:
  522.  * Dcntl(0xde02, "U:\DEV\FOO", &foo_descr): install a new device called
  523.  *     "FOO", which is described by the dev_descr structure "foo_descr".
  524.  *     this structure has the following fields:
  525.  *         DEVDRV *driver        the device driver itself
  526.  *       short  dinfo            info for the device driver
  527.  *       short  flags            flags for the file (e.g. O_TTY)
  528.  *       struct tty *tty        tty structure, if appropriate
  529.  *
  530.  * Dcntl(0xde00, "U:\DEV\BAR", n): install a new BIOS terminal device, with
  531.  *     BIOS device number "n".
  532.  * Dcntl(0xde01, "U:\DEV\BAR", n): install a new non-tty BIOS device, with
  533.  *     BIOS device number "n".
  534.  */
  535.  
  536. static long ARGS_ON_STACK 
  537. bios_fscntl(dir, name, cmd, arg)
  538.     fcookie *dir;
  539.     const char *name;
  540.     int cmd;
  541.     long arg;
  542. {
  543.     struct bios_file *b;
  544.  
  545.     UNUSED(dir);
  546.     if ((unsigned)cmd == DEV_INSTALL) {
  547.         struct dev_descr *d = (struct dev_descr *)arg;
  548.  
  549.         b = kmalloc(SIZEOF(struct bios_file));
  550.         if (!b) return 0;
  551.         strncpy(b->name, name, BNAME_MAX);
  552.         b->name[BNAME_MAX] = 0;
  553.         b->device = d->driver;
  554.         b->private = d->dinfo;
  555.         b->flags = d->flags;
  556.         b->tty = d->tty;
  557.         b->next = broot;
  558.         broot = b;
  559.         return (long)&kernelinfo;
  560.     }
  561.     if ((unsigned)cmd == DEV_NEWTTY) {
  562.         b = kmalloc(SIZEOF(struct bios_file));
  563.         if (!b) return ENSMEM;
  564.         b->tty = kmalloc(SIZEOF(struct tty));
  565.         if (!b->tty) {
  566.             kfree(b);
  567.             return ENSMEM;
  568.         }
  569.         strncpy(b->name, name, BNAME_MAX);
  570.         b->name[BNAME_MAX] = 0;
  571.         b->device = &bios_tdevice;
  572.         b->private = arg;
  573.         b->flags = O_TTY;
  574.         *b->tty = default_tty;
  575.         b->next = broot;
  576.         broot = b;
  577.         return 0;
  578.     }
  579.     if ((unsigned)cmd == DEV_NEWBIOS) {
  580.         b = kmalloc(SIZEOF(struct bios_file));
  581.         if (!b) return ENSMEM;
  582.         strncpy(b->name, name, BNAME_MAX);
  583.         b->name[BNAME_MAX] = 0;
  584.         b->tty = 0;
  585.         b->device = &bios_ndevice;
  586.         b->private = arg;
  587.         b->flags = 0;
  588.         b->next = broot;
  589.         return 0;
  590.     }
  591.     return EINVFN;
  592. }
  593.  
  594. static long ARGS_ON_STACK 
  595. bios_symlink(dir, name, to)
  596.     fcookie *dir;
  597.     const char *name, *to;
  598. {
  599.     struct bios_file *b;
  600.     long r;
  601.     fcookie fc;
  602.  
  603.     r = bios_lookup(dir, name, &fc);
  604.     if (r == 0) return EACCDN;    /* file already exists */
  605.     if (r != EFILNF) return r;    /* some other error */
  606.  
  607.     b = kmalloc(SIZEOF(struct bios_file));
  608.     if (!b) return EACCDN;
  609.  
  610.     strncpy(b->name, name, BNAME_MAX);
  611.     b->name[BNAME_MAX] = 0;
  612.     b->device = 0;
  613.     b->private = EINVFN;
  614.     b->flags = 0;
  615.     b->tty = kmalloc((long)strlen(to)+1);
  616.     if (!b->tty) {
  617.         kfree(b);
  618.         return EACCDN;
  619.     }
  620.     strcpy((char *)b->tty, to);
  621.     b->next = broot;
  622.     broot = b;
  623.     return 0;
  624. }
  625.  
  626. static long ARGS_ON_STACK 
  627. bios_readlink(fc, buf, buflen)
  628.     fcookie *fc;
  629.     char *buf;
  630.     int buflen;
  631. {
  632.     struct bios_file *b = (struct bios_file *)fc->index;
  633.  
  634.     if (!b) return EINVFN;
  635.     if (b->device) return EINVFN;
  636.  
  637.     strncpy(buf, (char *)b->tty, buflen);
  638.     if (strlen((char *)b->tty) >= buflen)
  639.         return ENAMETOOLONG;
  640.     return 0;
  641. }
  642.  
  643.  
  644. /*
  645.  * routines for file systems that don't support volume labels
  646.  */
  647.  
  648. long ARGS_ON_STACK 
  649. nowritelabel(dir, name)
  650.     fcookie *dir;
  651.     const char *name;
  652. {
  653.     UNUSED(dir);
  654.     UNUSED(name);
  655.     return EACCDN;
  656. }
  657.  
  658. long ARGS_ON_STACK 
  659. noreadlabel(dir, name, namelen)
  660.     fcookie *dir;
  661.     char *name;
  662.     int namelen;
  663. {
  664.     UNUSED(dir);
  665.     UNUSED(name);
  666.     UNUSED(namelen);
  667.     return EFILNF;
  668. }
  669.  
  670. /*
  671.  * routines for file systems that don't support links
  672.  */
  673.  
  674. long ARGS_ON_STACK 
  675. nosymlink(dir, name, to)
  676.     fcookie *dir;
  677.     const char *name, *to;
  678. {
  679.     UNUSED(dir); UNUSED(name);
  680.     UNUSED(to);
  681.     return EINVFN;
  682. }
  683.  
  684. long ARGS_ON_STACK 
  685. noreadlink(dir, buf, buflen)
  686.     fcookie *dir;
  687.     char *buf;
  688.     int buflen;
  689. {
  690.     UNUSED(dir); UNUSED(buf);
  691.     UNUSED(buflen);
  692.     return EINVFN;
  693. }
  694.  
  695. long ARGS_ON_STACK 
  696. nohardlink(fromdir, fromname, todir, toname)
  697.     fcookie *fromdir, *todir;
  698.     const char *fromname, *toname;
  699. {
  700.     UNUSED(fromdir); UNUSED(todir);
  701.     UNUSED(fromname); UNUSED(toname);
  702.     return EINVFN;
  703. }
  704.  
  705. /* dummy routine for file systems with no Fscntl commands */
  706.  
  707. long ARGS_ON_STACK 
  708. nofscntl(dir, name, cmd, arg)
  709.     fcookie *dir;
  710.     const char *name;
  711.     int cmd;
  712.     long arg;
  713. {
  714.     UNUSED(dir); UNUSED(name);
  715.     UNUSED(cmd); UNUSED(arg);
  716.     return EINVFN;
  717. }
  718.  
  719. /*
  720.  * Did the disk change? Not on this drive!
  721.  * However, we have to do Getbpb anyways, because someone has decided
  722.  * to force a media change on our (non-existent) drive.
  723.  */
  724. long ARGS_ON_STACK 
  725. nodskchng(drv)
  726.     int drv;
  727. {
  728.     (void)getbpb(drv);
  729.     return 0;
  730. }
  731.  
  732. long ARGS_ON_STACK 
  733. nocreat(dir, name, mode, attrib, fc)
  734.     fcookie *dir, *fc;
  735.     const char *name;
  736.     unsigned mode;
  737.     int attrib;
  738. {
  739.     UNUSED(dir); UNUSED(fc);
  740.     UNUSED(name); UNUSED(mode);
  741.     UNUSED(attrib);
  742.     return EACCDN;
  743. }
  744.  
  745. static DEVDRV * ARGS_ON_STACK 
  746. bios_getdev(fc, devsp)
  747.     fcookie *fc;
  748.     long *devsp;
  749. {
  750.     struct bios_file *b;
  751.  
  752.     b = (struct bios_file *)fc->index;
  753.  
  754.     if (b->device && b->device != &fakedev)
  755.         *devsp = (long)b->tty;
  756.     else
  757.         *devsp = b->private;
  758.  
  759.     return b->device;    /* return the device driver */
  760. }
  761.  
  762. /*
  763.  * NULL device driver
  764.  */
  765.  
  766. long ARGS_ON_STACK 
  767. null_open(f)
  768.     FILEPTR *f;
  769. {
  770.     UNUSED(f);
  771.     return 0;
  772. }
  773.  
  774. long ARGS_ON_STACK 
  775. null_write(f, buf, bytes)
  776.     FILEPTR *f; const char *buf; long bytes;
  777. {
  778.     UNUSED(f); UNUSED(buf);
  779.     return bytes;
  780. }
  781.  
  782. long ARGS_ON_STACK 
  783. null_read(f, buf, bytes)
  784.     FILEPTR *f; char *buf; long bytes;
  785. {
  786.     UNUSED(f); UNUSED(buf);
  787.     UNUSED(bytes);
  788.     return 0;
  789. }
  790.  
  791. long ARGS_ON_STACK 
  792. null_lseek(f, where, whence)
  793.     FILEPTR *f; long where; int whence;
  794. {
  795.     UNUSED(f); UNUSED(whence);
  796.     return (where == 0) ? 0 : ERANGE;
  797. }
  798.  
  799. long ARGS_ON_STACK 
  800. null_ioctl(f, mode, buf)
  801.     FILEPTR *f; int mode; void *buf;
  802. {
  803.     UNUSED(f);
  804.     if (mode == FIONREAD) {
  805.         *((long *)buf) = 0;
  806.     }
  807.     else if (mode == FIONWRITE)
  808.         *((long *)buf) = 1;
  809.     else
  810.         return EINVFN;
  811.     return 0;
  812. }
  813.  
  814. long ARGS_ON_STACK 
  815. null_datime(f, timeptr, rwflag)
  816.     FILEPTR *f;
  817.     short *timeptr;
  818.     int rwflag;
  819. {
  820.     UNUSED(f);
  821.     if (rwflag)
  822.         return EACCDN;
  823.     *timeptr++ = timestamp;
  824.     *timeptr = datestamp;
  825.     return 0;
  826. }
  827.  
  828. long ARGS_ON_STACK 
  829. null_close(f, pid)
  830.     FILEPTR *f;
  831.     int pid;
  832. {
  833.     UNUSED(f);
  834.     UNUSED(pid);
  835.     return 0;
  836. }
  837.  
  838. long ARGS_ON_STACK 
  839. null_select(f, p, mode)
  840.     FILEPTR *f; long p;
  841.     int mode;
  842. {
  843.     UNUSED(f); UNUSED(p);
  844.     UNUSED(mode);
  845.     return 1;    /* we're always ready to read/write */
  846. }
  847.  
  848. void ARGS_ON_STACK 
  849. null_unselect(f, p, mode)
  850.     FILEPTR *f;
  851.     long p;
  852.     int mode;
  853. {
  854.     UNUSED(f); UNUSED(p);
  855.     UNUSED(mode);
  856.     /* nothing to do */
  857. }
  858.  
  859. /*
  860.  * BIOS terminal device driver
  861.  */
  862.  
  863. static long ARGS_ON_STACK 
  864. bios_topen(f)
  865.     FILEPTR *f;
  866. {
  867.     f->flags |= O_TTY;
  868.     return 0;
  869. }
  870.  
  871. /*
  872.  * Note: when a BIOS device is a terminal (i.e. has the O_TTY flag
  873.  * set), bios_read and bios_write will only ever be called indirectly, via
  874.  * tty_read and tty_write. That's why we can afford to play a bit fast and
  875.  * loose with the pointers ("buf" is really going to point to a long) and
  876.  * why we know that "bytes" is divisible by 4.
  877.  */
  878.  
  879. static long ARGS_ON_STACK 
  880. bios_twrite(f, buf, bytes)
  881.     FILEPTR *f; const char *buf; long bytes;
  882. {
  883.     long *r;
  884.     long ret = 0;
  885.     int bdev = f->fc.aux;
  886.  
  887.     r = (long *)buf;
  888.     if (f->flags & O_NDELAY) {
  889.         while (bytes > 0) {
  890.             if (!bcostat(bdev)) break;
  891.             if (bconout(bdev, (int)*r) == 0)
  892.             break;
  893.             r++; bytes -= 4; ret+= 4;
  894.         }
  895.     } else {
  896.         while (bytes > 0) {
  897.             if (bconout(bdev, (int)*r) == 0)
  898.             break;
  899.             r++; bytes -= 4; ret+= 4;
  900.         }
  901.     }
  902. #if 0
  903.     (void)checkkeys();
  904. #endif
  905.     return ret;
  906. }
  907.  
  908. static long ARGS_ON_STACK 
  909. bios_tread(f, buf, bytes)
  910.     FILEPTR *f; char *buf; long bytes;
  911. {
  912.     long *r, ret = 0;
  913.     int bdev = f->fc.aux;
  914.  
  915.     r = (long *)buf;
  916.  
  917.     if ((f->flags & O_NDELAY)) {
  918.         while (bytes > 0) {
  919.             if ( !bconstat(bdev) )
  920.             break;
  921.             *r++ = bconin(bdev) & 0x7fffffffL;
  922.             bytes -= 4; ret += 4;
  923.         }
  924.     } else {
  925.         while (bytes > 0) {
  926.             *r++ = bconin(bdev) & 0x7fffffffL;
  927.             bytes -= 4; ret += 4;
  928.         }
  929.     }
  930.     return ret;
  931. }
  932.  
  933. /*
  934.  * read/write routines for BIOS devices that aren't terminals (like the
  935.  * printer & IKBD devices)
  936.  */
  937.  
  938. static long ARGS_ON_STACK 
  939. bios_nwrite(f, buf, bytes)
  940.     FILEPTR *f; const char *buf; long bytes;
  941. {
  942.     long ret = 0;
  943.     int bdev = f->fc.aux;
  944.     int c;
  945.  
  946.     while (bytes > 0) {
  947.         if ( (f->flags & O_NDELAY) && !bcostat(bdev) )
  948.             break;
  949.  
  950.         c = *buf++ & 0x00ff;
  951.  
  952.         if (bconout(bdev, c) == 0)
  953.             break;
  954.  
  955.         bytes--; ret++;
  956.     }
  957.     return ret;
  958. }
  959.  
  960. static long ARGS_ON_STACK 
  961. bios_nread(f, buf, bytes)
  962.     FILEPTR *f; char *buf; long bytes;
  963. {
  964.     long ret = 0;
  965.     int bdev = f->fc.aux;
  966.  
  967.     while (bytes > 0) {
  968.         if ( (f->flags & O_NDELAY) && !bconstat(bdev) )
  969.             break;
  970.         *buf++ = bconin(bdev) & 0xff;
  971.         bytes--; ret++;
  972.     }
  973.     return ret;
  974. }
  975.  
  976. /*
  977.  * BIOS terminal seek code -- this has to match the documented
  978.  * way to do isatty()
  979.  */
  980.  
  981. static long ARGS_ON_STACK 
  982. bios_tseek(f, where, whence)
  983.     FILEPTR *f;
  984.     long where;
  985.     int whence;
  986. {
  987.     UNUSED(f); UNUSED(where);
  988.     UNUSED(whence);
  989. /* terminals always are at position 0 */
  990.     return 0;
  991. }
  992.  
  993. #define MAXBAUD 16
  994.  
  995. /* keep these sorted in descending order */
  996. static long baudmap[MAXBAUD] = {
  997. 19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L,
  998. 600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L
  999. };
  1000.  
  1001. static long ARGS_ON_STACK 
  1002. bios_ioctl(f, mode, buf)
  1003.     FILEPTR *f; int mode; void *buf;
  1004. {
  1005.     long *r = (long *)buf;
  1006.     struct winsize *ws;
  1007.     char *aline;
  1008.     short dev;
  1009.     int i;
  1010.  
  1011.     if (mode == FIONREAD) {
  1012.         if (bconstat(f->fc.aux))
  1013.             *r = 1;
  1014.         else
  1015.             *r = 0;
  1016.     }
  1017.     else if (mode == FIONWRITE) {
  1018.         if (bcostat(f->fc.aux))
  1019.             *r = 1;
  1020.         else
  1021.             *r = 0;
  1022.     }
  1023.     else if (mode == TIOCFLUSH) {
  1024. /* BUG: this should flush the input/output buffers */
  1025.         return 0;
  1026.     }
  1027.     else if (mode == TIOCGWINSZ && f->fc.aux == 2) {
  1028.         aline = lineA0();
  1029.         ws = (struct winsize *)buf;
  1030.         ws->ws_row = *((short *)(aline - 42)) + 1;
  1031.         ws->ws_col = *((short *)(aline - 44)) + 1;
  1032.     } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) {
  1033.         long oldbaud, newbaud;
  1034.         dev = f->fc.aux;
  1035.  
  1036.         newbaud = *r;
  1037.         if (dev == 1 || dev >= 6) {
  1038.             if (has_bconmap)
  1039.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1040.             i = (int)rsconf(-2, -1, -1, -1, -1, -1);
  1041.             if (i < 0 || i >= MAXBAUD)
  1042.                 oldbaud = -1L;
  1043.             else
  1044.                 oldbaud = baudmap[i];
  1045.             *r = oldbaud;
  1046.             if (newbaud > 0) {
  1047.     /* BUG: assert DTR works only on modem1 */
  1048.                 if (dev == 1 || dev == 6) {
  1049.                     Offgibit(0xef);
  1050.                 }
  1051.                 for (i = 0; i < MAXBAUD; i++) {
  1052.                     if (baudmap[i] == newbaud) {
  1053.                         rsconf(i, -1, -1, -1, -1, -1);
  1054.                         return 0;
  1055.                     } else if (baudmap[i] < newbaud) {
  1056.                         *r = baudmap[i];
  1057.                         break;
  1058.                     }
  1059.                 }
  1060.                 return ERANGE;
  1061.             } else if (newbaud == 0L) {
  1062.     /* BUG: drop DTR: works only on modem1 */
  1063.                 if (dev == 1 || dev == 6) {
  1064.                     Ongibit(0x10);
  1065.                 }
  1066.             }
  1067.             return 0;
  1068.         } else if (dev == 2 || dev == 5) {
  1069.             /* screen: assume 9600 baud */
  1070.             oldbaud = 9600L;
  1071.         } else if (dev == 3) {
  1072.             /* midi */
  1073.             oldbaud = 31250L;
  1074.         } else {
  1075.             oldbaud = -1L;    /* unknown speed */
  1076.         }
  1077.         *r = oldbaud;
  1078.         if (newbaud > 0 && newbaud != oldbaud)
  1079.             return ERANGE;
  1080.         return 0;
  1081.     } else if (mode == TIOCCBRK || mode == TIOCSBRK) {
  1082.         unsigned long bits;
  1083.  
  1084.         dev = f->fc.aux;
  1085.         if (dev == 1 || dev >= 6) {
  1086.             if (has_bconmap)
  1087.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1088.         } else {
  1089.             return EINVFN;
  1090.         }
  1091.         bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1092.         bits = (bits >> 8) & 0x0ff;        /* isolate TSR byte */
  1093.         if (mode == TIOCCBRK)
  1094.             bits &= ~8;
  1095.         else
  1096.             bits |= 8;
  1097.         (void)rsconf(-1, -1, -1, -1, (int)bits, -1);
  1098.     } else if (mode == TIOCGFLAGS || mode == TIOCSFLAGS) {
  1099.         unsigned short oflags, flags;
  1100.         unsigned long bits;
  1101.         unsigned char ucr;
  1102.         short flow;
  1103.  
  1104.         dev = f->fc.aux;
  1105.         if (dev == 1 || dev >= 6) {
  1106.             oflags = ((struct tty *)f->devinfo)->sg.sg_flags;
  1107.             oflags &= (T_TANDEM|T_RTSCTS);
  1108.             if (has_bconmap)
  1109.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1110.             bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1111.             ucr = (bits >> 24L) & 0x0ff;        /* isolate UCR byte */
  1112.             oflags |= (ucr >> 3) & (TF_STOPBITS|TF_CHARBITS);
  1113.             if (ucr & 0x4) {            /* parity on? */
  1114.                 oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP;
  1115.             }
  1116.             if (mode == TIOCSFLAGS) {
  1117.                 flags = (*(unsigned short *)buf);
  1118.                 if (flags & T_EVENP) {
  1119.                     ucr |= 0x6;
  1120.                 } else if (flags & T_ODDP) {
  1121.                     ucr &= ~2;
  1122.                     ucr |= 0x4;
  1123.                 } else {
  1124.                     ucr &= ~6;
  1125.                 }
  1126.                 if (flags & TF_STOPBITS) {
  1127.                     ucr &= ~(0x18);
  1128.                     ucr |= (flags & TF_STOPBITS) << 3;
  1129.                 }
  1130.                 ucr &= ~(0x60);
  1131.                 ucr |= (flags & TF_CHARBITS) << 3;
  1132.                 flow = (flags & (T_RTSCTS|T_TANDEM)) >> 12L;
  1133.                 rsconf(-1, flow, ucr, -1, -1, -1);
  1134.             } else {
  1135.                 *((unsigned short *)buf) = oflags;
  1136.             }
  1137.         } else {
  1138.             return EINVFN;
  1139.         }
  1140.     } else if ((mode >= TCURSOFF && mode <= TCURSGRATE) && (f->fc.aux == 2)) {
  1141.         return Cursconf(mode - TCURSOFF, *((short *)buf));
  1142.     } else {
  1143.     /* Fcntl will automatically call tty_ioctl to handle
  1144.      * terminal calls that we didn't deal with
  1145.      */
  1146.         return EINVFN;
  1147.     }
  1148.     return 0;
  1149. }
  1150.  
  1151. static long ARGS_ON_STACK 
  1152. bios_select(f, p, mode)
  1153.     FILEPTR *f; long p; int mode;
  1154. {
  1155.     struct tty *tty = (struct tty *)f->devinfo;
  1156.     int dev = f->fc.aux;
  1157.  
  1158.     if (mode == O_RDONLY) {
  1159.         if (bconstat(dev)) {
  1160.             TRACE(("bios_select: data present for device %d", dev));
  1161.             return 1;
  1162.         }
  1163.         if (tty) {
  1164.         /* avoid collisions with other processes */
  1165.             if (!tty->rsel)
  1166.                 tty->rsel = p;
  1167.         }
  1168.         return 0;
  1169.     } else if (mode == O_WRONLY) {
  1170.         if (bcostat(dev)) {
  1171.             TRACE(("bios_select: ready to output on %d", dev));
  1172.             return 1;
  1173.         }
  1174.         if (tty) {
  1175.             if (!tty->wsel)
  1176.                 tty->wsel = p;
  1177.         }
  1178.         return 0;
  1179.     }
  1180.     /* default -- we don't know this mode, return 0 */
  1181.     return 0;
  1182. }
  1183.  
  1184. static void ARGS_ON_STACK 
  1185. bios_unselect(f, p, mode)
  1186.     FILEPTR *f;
  1187.     long p;
  1188.     int mode;
  1189. {
  1190.     struct tty *tty = (struct tty *)f->devinfo;
  1191.  
  1192.     if (tty) {
  1193.         if (mode == O_RDONLY && tty->rsel == p)
  1194.             tty->rsel = 0;
  1195.         else if (mode == O_WRONLY && tty->wsel == p)
  1196.             tty->wsel = 0;
  1197.     }
  1198. }
  1199.  
  1200. /*
  1201.  * mouse device driver
  1202.  */
  1203.  
  1204. #define MOUSESIZ 128*3
  1205. static unsigned char mousebuf[MOUSESIZ];
  1206. static int mousehead, mousetail;
  1207.  
  1208. long mousersel;    /* is someone calling select() on the mouse? */
  1209.  
  1210. char mshift;        /* shift key status; set by checkkeys() in bios.c */
  1211. short *gcurx = 0,
  1212.       *gcury = 0;    /* mouse pos. variables; used by big screen emulators */
  1213.  
  1214. void ARGS_ON_STACK 
  1215. mouse_handler(buf)
  1216.     const char *buf;    /* must be a *signed* character */
  1217. {
  1218.     unsigned char *mbuf, buttons;
  1219.     int newmtail;
  1220.     short dx, dy;
  1221.  
  1222. /* the Sun mouse driver has 0=down, 1=up, while the atari hardware gives
  1223.    us the reverse. also, we have the "middle" button and the "left"
  1224.    button reversed; so we use this table to convert (and also to add the
  1225.    0x80 to indicate a mouse packet)
  1226.  */
  1227.     static int _cnvrt[8] = {
  1228.         0x87, 0x86, 0x83, 0x82, 0x85, 0x84, 0x81, 0x80
  1229.     };
  1230.  
  1231.     mbuf = &mousebuf[mousetail];
  1232.     newmtail = mousetail + 3;
  1233.     if (newmtail >= MOUSESIZ)
  1234.         newmtail = 0;
  1235.     if (newmtail == mousehead)
  1236.         return;            /* buffer full */
  1237.  
  1238.     buttons = *buf++ & 0x7;        /* convert to SUN format */
  1239.     if (mshift & 0x3) {        /* a shift key held down? */
  1240.     /* if so, convert shift+button to a "middle" button */
  1241.         if (buttons == 0x1 || buttons == 0x2)
  1242.             buttons = 0x4;
  1243.         else if (buttons == 0x3)
  1244.             buttons = 0x7;
  1245.     }
  1246.     *mbuf++ = _cnvrt[buttons];    /* convert to Sun format */
  1247.     dx = *buf++;
  1248.     *mbuf++ = dx;            /* copy X delta */
  1249.     dy = *buf;
  1250.     *mbuf = -dy;            /* invert Y delta for Sun format */
  1251.     mousetail = newmtail;
  1252.     *gcurx += dx;            /* update line A variables */
  1253.     *gcury += dy;
  1254. /*
  1255.  * if someone has called select() waiting for mouse input, wake them
  1256.  * up
  1257.  */
  1258.     if (mousersel) {
  1259.         wakeselect(mousersel);
  1260.     }
  1261. }
  1262.  
  1263. extern void newmvec(), newjvec();    /* in intr.s */
  1264. static long oldvec = 0;
  1265. long oldjvec = 0;
  1266.  
  1267. static long ARGS_ON_STACK 
  1268. mouse_open(f)
  1269.     FILEPTR *f;
  1270. {
  1271.     char *aline;
  1272.  
  1273.     static char parameters[] = {
  1274.         0,         /* Y=0 in lower corner */
  1275.         0,        /* normal button handling */
  1276.         1, 1        /* X, Y scaling factors */
  1277.     };
  1278.  
  1279.     UNUSED(f);
  1280.  
  1281.     if (oldvec)        /* mouse in use */
  1282.         return EACCDN;
  1283.  
  1284. /* initialize pointers to line A variables */
  1285.     if (!gcurx) {
  1286.         aline = lineA0();
  1287.         if (aline == 0)    {    /* should never happen */
  1288.             ALERT("unable to read line A variables");
  1289.             return -1;
  1290.         }
  1291.         gcurx = (short *)(aline - 0x25a);
  1292.         gcury = (short *)(aline - 0x258);
  1293.         *gcurx = *gcury = 32;    /* magic number -- what MGR uses */
  1294.     }
  1295.  
  1296.     oldvec = syskey->mousevec;
  1297.     oldjvec = syskey->joyvec;    /* jr: save old joystick vector */
  1298.     Initmous(1, parameters, newmvec);
  1299.     syskey->joyvec = (long)newjvec;    /* jr: set up new joystick handler */
  1300.     mousehead = mousetail = 0;
  1301.     return 0;
  1302. }
  1303.  
  1304. static long ARGS_ON_STACK 
  1305. mouse_close(f, pid)
  1306.     FILEPTR *f;
  1307.     int pid;
  1308. {
  1309.     static char parameters[] = {
  1310.         0,         /* Y=0 in lower corner */
  1311.         0,        /* normal button handling */
  1312.         1, 1        /* X, Y scaling factors */
  1313.     };
  1314.  
  1315.     UNUSED(pid);
  1316.     if (!f) return EIHNDL;
  1317.     if (f->links <= 0) {
  1318.         if (!oldvec) {
  1319.             DEBUG(("Mouse not open!!"));
  1320.             return -1;
  1321.         }
  1322.         Initmous(1, parameters, (void *)oldvec);    /* gratuitous (void *) for Lattice */
  1323.         syskey->joyvec = oldjvec;    /* jr: restore old joystick handler */
  1324.         oldvec = 0;
  1325.     }
  1326.     return 0;
  1327. }
  1328.  
  1329. static long ARGS_ON_STACK 
  1330. mouse_read(f, buf, nbytes)
  1331.     FILEPTR *f;
  1332.     char *buf;
  1333.     long nbytes;
  1334. {
  1335.     long count = 0;
  1336.     int mhead;
  1337.     unsigned char *foo;
  1338.  
  1339.     mhead = mousehead;
  1340.     foo = &mousebuf[mhead];
  1341.  
  1342.     if (mhead == mousetail) {
  1343.         if (f->flags & O_NDELAY)
  1344.             return 0;
  1345.         do {
  1346.             yield();
  1347.         } while (mhead == mousetail);
  1348.     }
  1349.  
  1350.     while ( (mhead != mousetail) && (nbytes > 0)) {
  1351.         *buf++ = *foo++;
  1352.         mhead++;
  1353.         if (mhead >= MOUSESIZ) {
  1354.             mhead = 0;
  1355.             foo = mousebuf;
  1356.         }
  1357.         count++;
  1358.         --nbytes;
  1359.     }
  1360.     mousehead = mhead;
  1361.     return count;
  1362. }
  1363.  
  1364. static long ARGS_ON_STACK 
  1365. mouse_ioctl(f, mode, buf)
  1366.     FILEPTR *f;
  1367.     int mode;
  1368.     void *buf;
  1369. {
  1370.     long r;
  1371.  
  1372.     UNUSED(f);
  1373.     if (mode == FIONREAD) {
  1374.         r = mousetail - mousehead;
  1375.         if (r < 0) r += MOUSESIZ;
  1376.         *((long *)buf) = r;
  1377.     }
  1378.     else
  1379.         return EINVFN;
  1380.     return 0;
  1381. }
  1382.  
  1383. static long ARGS_ON_STACK 
  1384. mouse_select(f, p, mode)
  1385.     FILEPTR *f;
  1386.     long p;
  1387.     int mode;
  1388. {
  1389.     UNUSED(f);
  1390.  
  1391.     if (mode != O_RDONLY)
  1392.         return 1;    /* we can always take output :-) */
  1393.  
  1394.     if (mousetail - mousehead)
  1395.         return 1;    /* input waiting already */
  1396.  
  1397.     if (!mousersel)
  1398.         mousersel = p;
  1399.     return 0;
  1400. }
  1401.  
  1402. static void ARGS_ON_STACK 
  1403. mouse_unselect(f, p, mode)
  1404.     FILEPTR *f;
  1405.     long p;
  1406.     int mode;
  1407. {
  1408.     UNUSED(f);
  1409.  
  1410.     if (mode == O_RDONLY && mousersel == p)
  1411.         mousersel = 0;
  1412. }
  1413.  
  1414.  
  1415. /*
  1416.  * UTILITY ROUTINE called by Bconmap() in xbios.c:
  1417.  * this sets handle -1 of process p to a file handle
  1418.  * that has BIOS device "dev". Returns 0 on failure,
  1419.  * non-zero on success.
  1420.  */
  1421.  
  1422. int
  1423. set_auxhandle(p, dev)
  1424.     PROC *p;
  1425.     int dev;
  1426. {
  1427.     FILEPTR *f;
  1428.     struct bios_file *b;
  1429.  
  1430.     f = new_fileptr();
  1431.     if (f) {
  1432.         f->links = 1;
  1433.         f->flags = O_RDWR;
  1434.         f->pos = 0;
  1435.         f->devinfo = 0;
  1436.         f->fc.fs = &bios_filesys;
  1437.         f->fc.aux = dev;
  1438.         f->fc.dev = BIOSDRV;
  1439.         for (b = broot; b; b = b->next) {
  1440.             if (b->private == dev &&
  1441.                 (b->device == &bios_tdevice ||
  1442.                  b->device == &bios_ndevice)) {
  1443.                 f->fc.index = (long)b;
  1444.                 f->dev = b->device;
  1445.                 if (b->device != &fakedev)
  1446.                     f->devinfo = (long)b->tty;
  1447.                 goto found_device;
  1448.             }
  1449.         }
  1450.         f->fc.index = 0;
  1451.         f->dev = &bios_ndevice;
  1452. found_device:
  1453.         if ((*f->dev->open)(f) < 0) {
  1454.             f->links = 0;
  1455.             dispose_fileptr(f);
  1456.             return 0;
  1457.         }
  1458.     } else {
  1459. /* no memory! use the fake FILEPTR we
  1460.  * set up in biosfs_init
  1461.  */
  1462.         f = defaultaux;
  1463.         f->links++;
  1464.     }
  1465.  
  1466.     (void)do_pclose(p, p->aux);
  1467.     p->aux = f;
  1468.  
  1469.     return 1;
  1470. }
  1471.